<template>
  <edit-card :title="title" :type="type" :loading="globalLoading" @confirm="submitForm">
    <a-anchor
      style="position: absolute; top: 16px; right: 16px; width: 112px"
      :items="[
        { key: '1', href: '#components-anchor-demo-basic', title: '模型详情' },
        { key: '2', href: '#components-anchor-demo-static', title: '参数配置' }
      ]"
      wrapper-class="a-anchor-class"
      :target-offset="500"
      :offset-top="80 + 54"
      @click.prevent
    />

    <div id="components-anchor-demo-basic" class="default-class-title">模型详情</div>
    <div class="edit-task">
      <a-form
        ref="caseFormRef"
        :model="formState"
        :rules="caseRules"
        :label-col="{ style: { width: '120px' } }"
        class="w-560"
        label-align="left"
      >
        <a-form-item label="名称" name="modelName">
          <a-input v-model:value="formState.modelName" v-trim class="w-440" placeholder="请输入模型名称" :maxlength="200" />
        </a-form-item>

        <a-form-item label="标签" name="labelIds">
          <a-select
            v-model:value="formState.labelIds"
            class="w-440"
            :show-search="false"
            :options="statusOptions"
            :field-names="{ label: 'labelName', value: 'labelIds' }"
            mode="multiple"
            max-tag-count="responsive"
            placeholder="请选择标签"
            style="width: 100%"
            show-arrow
          />
        </a-form-item>
        <a-form-item label="镜像" name="imageId">
          <a-select
            v-model:value="formState.imageId"
            :options="imageList"
            placeholder="请选择镜像"
            :field-names="{ label: 'imageName', value: 'id' }"
            class="w-440"
            @change="imageSelect"
          />
        </a-form-item>
        <a-form-item label="算法框架" name="frame">
          <g-input v-trim :value="formState.frame" :search="false" disabled class="w-440" placeholder="" />
        </a-form-item>

        <a-form-item label="描述" name="description">
          <a-textarea
            v-model:value="formState.description"
            v-trim
            class="w-440"
            placeholder="请输入描述"
            :rows="5"
            :maxlength="200"
            show-count
          />
        </a-form-item>

        <a-form-item label="模型文档" name="docUrl">
          <file-upload
            v-model:file-url="formState.docUrl"
            class="file-upload w-440"
            :max-count="1"
            :is-preview="false"
            accept="pdf,ppt,pptx,doc,docx"
            suffix="doc"
            :module-prefix="'model'"
          >
            <a-button class="icon-with-btn btn-mini" type="dashed" size="small">
              <i class="iconfont icon-upload-line"></i>
              上传
            </a-button>
          </file-upload>
        </a-form-item>

        <a-form-item label="模型代码" name="sourceUrl">
          <file-upload
            v-model:file-url="formState.sourceUrl"
            class="file-upload w-440"
            :max-count="1"
            :is-preview="false"
            suffix="zip"
            accept="zip"
            :module-prefix="'model'"
            @upload-success-after="onUpdateFile"
          >
            <a-button class="icon-with-btn btn-mini" type="dashed" size="small">
              <i class="iconfont icon-upload-line"></i>
              上传压缩包
            </a-button>
          </file-upload>
        </a-form-item>

        <a-form-item label="模型文件" name="modelFileUrl">
          <file-upload
            v-model:file-url="formState.modelFileUrl"
            class="w-440"
            :max-count="1"
            :is-preview="false"
            :module-prefix="'model'"
            :is-open-file-accept-verify="false"
          >
            <a-button class="icon-with-btn btn-mini" type="dashed" size="small">
              <i class="iconfont icon-upload-line"></i>
              上传
            </a-button>
          </file-upload>
        </a-form-item>
      </a-form>
    </div>

    <div id="components-anchor-demo-static" class="default-class-title mt-120">参数配置</div>

    <div class="edit-task">
      <params-form />
    </div>
  </edit-card>
</template>

<script lang="ts" setup>
  import { message } from 'ant-design-vue'
  import type { Rule } from 'ant-design-vue/es/form'
  import { SelectValue } from 'ant-design-vue/es/select'
  import { computed, ref } from 'vue'
  import { useRequest } from 'vue-request'
  import { useRoute, useRouter } from 'vue-router'

  import FileUpload from '@/components/upload/FileUpload/index.vue'
  import { adminModelManageApi, mirrorManageApi, tagManageApi } from '@/services/api'
  import { validateDirName } from '@/utils'
  import { countStrToBit } from '@/utils'

  import { CPU_OPTIONS, GPU_OPTIONS, REQUEST_TYPE_OPTIONS } from '../options'
  import { CommonModelLabelVO, DictionaryType, Form, ModelDetailsType, TaskStatus } from '../types'
  import ParamsForm from './components/params-form.vue'

  const route = useRoute()
  const router = useRouter()
  const caseId = route.params.id as string | ''

  const detailData = ref<ModelDetailsType | {}>({})

  const type = ref((caseId ? 'edit' : 'add') as 'edit' | 'add')

  const title = computed(() => {
    return caseId ? `编辑模型（${detailData.value.modelName || ''}）` : '新建模型'
  })

  const globalLoading = computed(() => {
    return getDictionLoading.value || getDetailLoading.value || addLoading.value || updateLoading.value || pageLoading.value
  })

  /* 模型详情表单 -------------------------------------------------------------------------- */
  const caseFormRef = ref()
  let statusOptions = ref<TaskStatus[]>([])
  const formState = ref<Form>({
    modelName: '',
    labelIds: [],
    imageId: undefined,
    frame: '',
    description: '',
    docUrl: '',
    modelFileUrl: '',
    sourceUrl: '',
    modelSize: undefined
  })

  const validateByte = async (rule: Rule, value: string) => {
    const byteCount = countStrToBit(value)
    if (byteCount === 0) {
      return Promise.reject('请输入模型名称')
    } else if (byteCount > 200) {
      return Promise.reject('名称不可超过200字节')
    }
    return Promise.resolve()
  }
  const caseRules: Record<string, Rule[]> = {
    modelName: [{ validator: validateDirName() }, { required: true, trigger: 'change', validator: validateByte }],
    labelIds: [{ required: true, message: '请选择标签' }],
    imageId: [{ required: true, message: '请选择镜像' }],
    frame: [{ required: true }],
    docUrl: [{ required: true, message: '请上传模型文档', trigger: 'change' }],
    sourceUrl: [{ required: true, message: '请上传模型代码', trigger: 'change' }]
  }

  // 获取镜像数据/选择逻辑
  const imageList = ref()
  const { loading: pageLoading, runAsync: runGetImageList } = useRequest(mirrorManageApi.imageCommon, {
    onSuccess: (data: any) => {
      imageList.value = data.data
    }
  })
  runGetImageList({ dockerPurposeType: 1 })

  const imageSelect = (val: any) => {
    formState.value.frame = imageList.value.find((item: any) => item.id === val)?.frame
    caseFormRef.value?.validate('frame')
  }

  // 增加运行参数
  const addParam = (type: 1 | 2 | 3) => {
    let pushData = {
      paramName: '',
      paramValue: '',
      canDelete: true
    }
    if (type === 1) {
      formState.value.runParams.push(pushData)
      return
    }
    if (type === 2) {
      formState.value.inputParams.push(pushData)
      return
    }
    if (type === 3) {
      formState.value.outputParams.push(pushData)
    }
  }

  //删除运行参数
  const removeParamInput = (type: 1 | 2 | 3, index: number) => {
    if (type === 1) {
      formState.value.runParams.splice(index, 1)
      return
    }
    if (type === 2) {
      formState.value.inputParams.splice(index, 1)
      return
    }
    if (type === 3) {
      formState.value.outputParams.splice(index, 1)
    }
  }

  //获取分类字典信息
  const { loading: getDictionLoading, runAsync: getDictionaryRun } = useRequest<ResponseData<DictionaryType[]>>(tagManageApi.list, {
    onSuccess: ({ data }) => {
      statusOptions.value = [
        ...statusOptions.value,
        ...data.map((item: DictionaryType) => ({ labelName: item.v, labelIds: item.id }))
      ] as TaskStatus[]
    }
  })
  getDictionaryRun({
    type: 'common_model'
  })

  // 上传模型代码时监听文档是否改变
  const onUpdateFile = (file: any) => {
    formState.value.modelSize = file.size
    console.log(typeof file.size, 'typeof file.size')
  }

  /* 表单提交/详情 -------------------------------------------------------------------------- */
  const { loading: addLoading, runAsync: runAddAsync } = useRequest(adminModelManageApi.add)
  const { loading: updateLoading, runAsync: runUpdateAsync } = useRequest(adminModelManageApi.update)

  // TODO:确定
  const submitForm = async () => {
    await caseFormRef.value?.validate()
    // await resourceRef.value?.validate()
    // ...resourceForm.value
    const params = { ...formState.value }
    const isAdd = type.value === 'add'
    try {
      await (isAdd ? runAddAsync(params, { isAddUid: true }) : runUpdateAsync({ ...params, id: caseId }, { isAddUid: true }))
      message.success('操作成功')
      goBack()
    } catch (error) {
      console.log(error)
    }
  }

  const goBack = () => {
    router.go(-1)
  }

  //获取详情数据
  const { loading: getDetailLoading, runAsync: runGetCaseDetail } = useRequest<ResponseData<ModelDetailsType>>(
    (id: string) => adminModelManageApi.detail(id)(),
    {
      onSuccess: ({ data }) => {
        console.log('详情', data)

        Object.assign(detailData.value, data)
        Object.assign(formState.value, data, {
          labelIds: data.commonModelLabelVOList ? data.commonModelLabelVOList.map((item: CommonModelLabelVO) => item.labelId) : []
        })
        // resourceForm.value.cpu = data.cpu
        // resourceForm.value.gpu = data.gpu
        // resourceForm.value.memory = data.memory
        // resourceForm.value.cpuMemory = `${data.cpu}-${data.memory}`
        Reflect.deleteProperty(formState.value, 'updateTime')
      }
    }
  )
  const getDetailData = (id: string) => {
    runGetCaseDetail(id)
  }
  type.value === 'edit' && getDetailData(caseId)
</script>
<style lang="less" scoped>
  .default-class-title {
    .font20b();

    position: relative;
    margin-bottom: 50px;

    &::before {
      position: absolute;
      top: 50%;
      left: -16px;
      width: 3px;
      height: 22px;
      background: #1868e9;
      border-radius: 0 2px 2px 0;
      content: '';
      transform: translateY(-50%);
      flex: none;
      order: 0;
      align-self: stretch;
      flex-grow: 0;
    }
  }

  .a-anchor-class {
    position: absolute !important;
    top: 54px;
    right: 10;
  }

  .edit-task {
    :deep(.ant-form-item) {
      margin-bottom: 40px;
    }

    :deep(.ant-form-item-label > label::after) {
      display: none;
    }

    :deep(.ant-radio-wrapper) {
      margin-right: 24px;
    }

    .ant-radio-wrapper :deep(.ant-transfer-list) {
      position: relative;

      .ant-transfer-list-header {
        height: 39px;
        background: #fafafa;
      }

      &:first-child {
        .ant-transfer-list-header {
          &::after {
            content: '待选';
            position: absolute;
            right: 8px;
          }
        }
      }

      &:last-child {
        .ant-transfer-list-header {
          &::after {
            content: '已选';
            position: absolute;
            right: 8px;
          }
        }
      }

      .ant-input-affix-wrapper {
        height: 32px;
        min-height: 32px !important;
      }
    }

    .tag-select {
      display: flex;

      .left {
        margin-right: 80px;
      }
    }
  }
</style>
